package com.lsh.ofc.core.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lsh.base.common.exception.BusinessException;
import com.lsh.ofc.core.constant.Constants;
import com.lsh.ofc.core.entity.*;
import com.lsh.ofc.core.enums.*;
import com.lsh.ofc.core.exception.EC;
import com.lsh.ofc.core.service.OfcCustomerService;
import com.lsh.ofc.core.service.OfcSoSplitService;
import com.lsh.ofc.core.service.OfcSupplierService;
import com.lsh.ofc.core.service.SupplierConfigService;
import com.lsh.ofc.proxy.context.WumartBasicContext;
import com.lsh.ofc.proxy.model.Goods;
import com.lsh.ofc.proxy.service.AtpServiceProxy;
import com.lsh.ofc.proxy.service.GoodsServiceProxy;
import com.lsh.ofc.proxy.service.SupplyInfoServiceProxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author huangdong
 * @date 16/9/9
 */
@Service
public class OfcSoSplitServiceImpl implements OfcSoSplitService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private AtpServiceProxy atpServiceProxy;

    @Autowired
    private GoodsServiceProxy goodsServiceProxy;

    @Autowired
    private OfcSupplierService ofcSupplierService;

    @Autowired
    private OfcCustomerService ofcCustomerService;

    @Autowired
    private SupplyInfoServiceProxy supplyInfoServiceProxy;

    @Resource
    private SupplierConfigService supplierConfigService;


    @Override
    public List<OfcSoHead> split(OfcOrderHead order) throws BusinessException {
        Long orderCode = order.getOrderCode();
        JSONObject headExtJson = JSON.parseObject(order.getExt());
        logger.info("orderCode {} ext is {}", orderCode, headExtJson.toJSONString());
        Long parentOrderCode = headExtJson.getLong("parent_order_code");
        String providerId = headExtJson.getString("provider_id");

        String supplierGroupId = headExtJson.getString("supplier_group_id");
        String orderClass = headExtJson.getString("order_class");

        Long atpOrderCode = orderCode;
        if (parentOrderCode != null && !parentOrderCode.equals(0L)) {
            atpOrderCode = parentOrderCode;
        }

        List<OfcOrderDetail> details = order.getDetails();
        logger.info("订单【" + orderCode + "】查询ATP扣减信息开始...atpOrderCode = " + atpOrderCode);
        Map<Long, Map<String, BigDecimal>> skuDcQtyMap = this.atpServiceProxy.querySkuDcQtyMap(atpOrderCode, orderClass);
        logger.info("订单【" + orderCode + "】查询ATP扣减信息结果，skuDcQtyMap=" + skuDcQtyMap);

        Map<String, OfcSoHead> soMap = new HashMap<>();
        for (OfcOrderDetail item : details) {
            Long skuCode = item.getSkuCode();

            BigDecimal skuQty = item.getSkuQty();
            if (skuQty == null || skuQty.compareTo(BigDecimal.ZERO) <= 0) {
                continue;
            }
            Map<String, BigDecimal> dcQtyMap = skuDcQtyMap.get(skuCode);
            if (CollectionUtils.isEmpty(dcQtyMap)) {
                throw EC.ERROR.exception("订单商品库存扣减信息不存在! sku_code=" + skuCode);
            }

            Iterator<Map.Entry<String, BigDecimal>> it = dcQtyMap.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, BigDecimal> decimalEntry = it.next();
                String supplyMarketDc = decimalEntry.getKey();
                String[] splits = supplyMarketDc.split(":");
                if (splits.length != 3) {
                    throw EC.ERROR.exception("订单商品库存扣减信息不存在! sku_code=" + skuCode);
                }

                String market = splits[1];

                if (!providerId.equals(market)) {
                    it.remove();
                }
            }

            //单DC扣减
            if (dcQtyMap.size() != 1) {
                throw EC.ERROR.exception("订单商品库存扣减信息不存在! sku_code=" + skuCode);
            }

            String dcSupply = dcQtyMap.entrySet().iterator().next().getKey();
            String[] dcSupplys = dcSupply.split(":");
            String dc;
            Integer market;
            Integer supply;
            if (dcSupplys == null) {
                throw EC.ERROR.exception("订单商品库存扣减信息有误! sku_code=" + skuCode);
            }
            dc = dcSupplys[0];
            if (dcSupplys.length != 3) {
                throw EC.ERROR.exception("订单商品库存扣减信息有误! dcSupply = " + dcSupply);
            } else {
                market = Integer.valueOf(dcSupplys[1]);
                supply = Integer.valueOf(dcSupplys[2]);
            }

            //TODO:地区Region
            Integer regionCode = order.getRegionCode();
            OfcSoHead so = soMap.get(dcSupply);
            if (so == null) {
                logger.info("dc = " + dc + ",regionCode = " + regionCode + ",supply = " + supply + " , market = " + market);
                OfcSupplier supplier = supplierConfigService.findSupplier(market, dc, supplierGroupId, supply, regionCode);
                if (supplier == null) {
                    throw EC.ERROR.exception("OFC供货商信息不存在! code=" + dc);
                }
                logger.info("ofc supplier is {}", JSON.toJSONString(supplier));
                String supplierConfig = supplier.getConfig();
                JSONObject supplierConfigJSON = JSON.parseObject(supplierConfig);
                Integer cusType = supplierConfigJSON.getInteger(WumartBasicContext.CUSTYPE);
                Integer wumartFill = supplierConfigJSON.getInteger(WumartBasicContext.WUMART_FILL);
                Integer soOrderType = supplierConfigJSON.getInteger(WumartBasicContext.SO_ORDER_TYPE);
                String soDistributionType = supplierConfigJSON.getString(WumartBasicContext.SO_DISTRIBUTION_TYPE);
                Integer saleModel = supplierConfigJSON.getInteger("saleModel");
                Integer deliveryType = supplierConfigJSON.getInteger("deliveryType");
                Integer wgFill = supplierConfigJSON.getInteger(WumartBasicContext.WG_FILL);
                if (null == cusType) {
                    cusType = CusType.LSH_NEW.getValue();
                }
                if (null == wumartFill) {
                    wumartFill = WumartFill.IS_NOT_WUMARKT_FILL.getValue();
                }

                if (null == wgFill) {
                    wgFill = 0;
                }

                if (null == soOrderType) {
                    soOrderType = SoOrderType.NOT_PRE_SALE.getValue();
                }

                if (null == soDistributionType) {
                    soDistributionType = DistributionType.ORDER_SO.getCode();
                }

                JSONObject ext = JSON.parseObject(order.getExt());
                ext.put(Constants.SO_H_SUPPLIER_CODE, supplier.getCode());
                ext.put(WumartBasicContext.WUMART_FILL, wumartFill);
                ext.put(WumartBasicContext.WG_FILL, wgFill);
                // ext存履约客户号类型
                ext.put(WumartBasicContext.CUSTYPE, cusType);
                /**
                 * SO 是否预售单  0 非预售单 1 预售单
                 */
                ext.put(WumartBasicContext.SO_ORDER_TYPE, soOrderType);
                // 履约环节才能知道具体客户号用哪个，从order_head.ext去掉
                OfcCustomer customer = this.getCustomer(order, cusType);
                ext.put(Constants.ORDER_H_MP_CUST_CODE, customer.getMpCustCode());

                ext.put("saleModel", saleModel);
                ext.put("deliveryType", deliveryType);

                so = new OfcSoHead();
                so.setOrderCode(orderCode);
                so.setVenderId(order.getVenderId());
                so.setOrderTime(order.getOrderTime());
                so.setRegionCode(order.getRegionCode());
                so.setAddressCode(order.getAddressCode());
                so.setWarehouseCode(supplier.getWarehouseCode());
                so.setWarehouseName(supplier.getWarehouseName());

                so.setSupplierId(supplier.getSupplierId());
                so.setSupplierDc(supplier.getSupplierDc());
                so.setSupplierOrg(supplier.getSupplierOrg());
                so.setSupplierCode(supplier.getCode());
                so.setSupplierGroup(supplier.getSupplierGroup());

                so.setFulfillWms(supplier.getFulfillWms());
                so.setFulfillChannel(supplier.getFulfillChannel());
                so.setSoStatus(SoStatus.UNCREATED.getValue());
                so.setTotalSkuOrderQty(BigDecimal.ZERO);
                so.setExt(ext.toJSONString());
                so.setSecondDistributionFlag(order.getSecondDistributionFlag());
                so.setDistributionWay(order.getDistributionWay());
                so.setOrderDistributionType(soDistributionType);
                so.setPreWarehouseCode(order.getPreWarehouseCode());
                so.setDetails(new ArrayList<OfcSoDetail>());
                soMap.put(dcSupply, so);
            }

            OfcSoDetail detail = new OfcSoDetail();
            detail.setGoodsCode(item.getGoodsCode());
            detail.setGoodsName(item.getGoodsName());
            detail.setGoodsSaleUnit(item.getGoodsSaleUnit());
            detail.setGoodsPrice(item.getGoodsPrice());
            detail.setGoodsAmount(item.getGoodsAmount());
            detail.setSkuCode(skuCode);
            detail.setItemCode(item.getItemCode());
            detail.setVenderId(item.getVenderId());
            detail.setSkuOrderQty(skuQty);
            detail.setExt(item.getExt());
            so.getDetails().add(detail);

            so.setTotalSkuOrderQty(so.getTotalSkuOrderQty().add(item.getSkuQty()));
        }

        Map<Long, Integer> skuDefineMap = new HashMap<>(16);
        for (OfcSoHead so : soMap.values()) {
            int i = 0;
            Set<Long> goodsCodes = new HashSet<>();
            for (OfcSoDetail detail : so.getDetails()) {
                detail.setItemNo((++i) * 10);
                goodsCodes.add(detail.getGoodsCode());
            }

//            Integer supplierMarket = so.getSupplierId();
//            String supplierDc = so.getSupplierDc();
            Integer supplierOrg = so.getSupplierOrg();
            logger.info("订单【" + orderCode + "】【supplierOrg = " + supplierOrg + "】查询商品信息开始，goodsCodes= " + goodsCodes);
//            Map<Long, Goods> goodsMap = this.goodsServiceProxy.getGoodsInfoMapByGoodsCodes(goodsCodes, supplierMarket, supplierOrg, supplierDc, order.getVenderId());
            Map<Long, Goods> goodsMap = this.goodsServiceProxy.getGoodsInfoMapByGoodsCodesItem(goodsCodes, order.getVenderId());
            logger.info("订单【" + orderCode + "】【supplierOrg = " + supplierOrg + "】查询商品信息结果，goodsMap=" + JSON.toJSONString(goodsMap));
            Set<String> outSkuCodes = new HashSet<>();
            for (Goods goods : goodsMap.values()) {
                if (StringUtils.isEmpty(goods.getSupplySkuCode())) {
                    throw EC.ERROR.exception("该商品没有对应的物美码! goods = " + JSON.toJSONString(goods));
                }
                outSkuCodes.add(goods.getSupplySkuCode());
            }

            if (outSkuCodes.size() <= 0) {
                throw EC.ERROR.exception("供货码集合为空!");
            }

            for (OfcSoDetail detail : so.getDetails()) {
                Long goodsCode = detail.getGoodsCode();
                Goods goods = goodsMap.get(goodsCode);
                if (goods == null) {
                    throw EC.ERROR.exception("商品不存在! goods_code=" + goodsCode);
                }

                String ext = detail.getExt();
                JSONObject extJson;
                if (StringUtils.isEmpty(ext)) {
                    extJson = new JSONObject();
                } else {
                    extJson = JSON.parseObject(ext);
                }
                extJson.put(Constants.ORDER_D_SKU_DEFINE, goods.getSkuDefine());
                extJson.put(Constants.ORDER_D_SKU_PACK_UNIT, goods.getPurchaseUnitNu());
                extJson.put(Constants.ORDER_D_SKU_PACK_NAME, goods.getPurchaseUnit());

                detail.setSkuSupplyCode(goods.getSupplySkuCode());
                this.fillTaxRate(detail);
                skuDefineMap.put(goodsCode, goods.getSkuDefine());
//                //填充供货价
//                BigDecimal supplyPrice = goods.getSupplyPrice();
//                if (supplyPrice == null) {
//                    throw EC.ERROR.exception("商品供货价为空或数据不合法！商品销售码=" + goodsCode + " ,supplyPrice = " + supplyPrice + "，code = " + detail.getSkuSupplyCode());
//                }

//                if (supplyPrice.compareTo(BigDecimal.ZERO) < 0) {
//                    extJson.put("mvp", supplyPrice.toString());
//                    supplyPrice = BigDecimal.ZERO;
//                }

                detail.setExt(extJson.toJSONString());
                detail.setSkuSupplyPrice(new BigDecimal("0.01"));
            }
        }

        for (OfcOrderDetail item : details) {
            this.fillSkuDefine(item, skuDefineMap);
        }
        // 物美在库直流拆单
        soMap = this.split4lgortType(soMap);

        return new ArrayList<>(soMap.values());
    }

    /**
     * 物美在库直流拆单
     *
     * @param soMap
     * @return
     */
    private Map<String, OfcSoHead> split4lgortType(Map<String, OfcSoHead> soMap) {

        Map<String, OfcSoHead> soHeadMap = new HashMap<>();
        for (Map.Entry<String, OfcSoHead> soHeadEntry : soMap.entrySet()) {
            String soKey = soHeadEntry.getKey();
            OfcSoHead soHead = soHeadEntry.getValue();
            Integer fulfillChannel = soHead.getFulfillChannel();
            // 不是履约物美so
            if (!fulfillChannel.equals(FulfillChannel.WUMART_OFC.getValue())) {
                soHeadMap.put(soKey, soHead);
                continue;
            }

            // 直流在库拆单
            List<OfcSoDetail> soDetailList = soHead.getDetails();
            Set<String> supplyCodes = new HashSet<>();
            for (OfcSoDetail soDetail : soDetailList) {
                supplyCodes.add(soDetail.getSkuSupplyCode());
            }
            // 请求 拆单规则接口<code, lgortType>
            Map<String, Integer> splitDetailMap = supplyInfoServiceProxy.getSupplyInfoByCodes(supplyCodes, soHead.getSupplierDc(), soHead.getVenderId());

            if (null == splitDetailMap || splitDetailMap.isEmpty()) {
                throw EC.ERROR.exception("物美在库or直流拆单so,请求基础服务返回数据失败！soHead bill code  =" + soHead.getSoBillCode());
            }

            //在库，直流 详情
            for (OfcSoDetail soDetail : soDetailList) {
                Integer lgortType = splitDetailMap.get(soDetail.getSkuSupplyCode());
                if (null == lgortType) {
                    throw EC.ERROR.exception("物美在库or直流拆单so,请求基础服务返回数据！没有在库直流属性 code  =" + soDetail.getSkuSupplyCode());
                }

                String soHeadKey = soKey + ":" + lgortType;
                OfcSoHead targetSoHead = soHeadMap.get(soHeadKey);
                if (null == targetSoHead) {
                    targetSoHead = new OfcSoHead();

                    BeanUtils.copyProperties(soHead, targetSoHead);
                    targetSoHead.setTotalSkuOrderQty(BigDecimal.ZERO);
                    targetSoHead.setDetails(new ArrayList<OfcSoDetail>());

                    JSONObject ext = JSON.parseObject(targetSoHead.getExt());
                    ext.put(Constants.SO_H_LGORT_TYPE, lgortType);
                    targetSoHead.setExt(ext.toJSONString());
                    //
                    soHeadMap.put(soHeadKey, targetSoHead);
                }

                targetSoHead.getDetails().add(soDetail);
                targetSoHead.setTotalSkuOrderQty(targetSoHead.getTotalSkuOrderQty().add(soDetail.getSkuOrderQty()));
            }
        }

        for (OfcSoHead so : soHeadMap.values()) {
            int i = 0;
            for (OfcSoDetail detail : so.getDetails()) {
                detail.setItemNo((++i) * 10);
            }
        }

        return soHeadMap;
    }

    /**
     * 履约模式拆单
     *
     * @param soMap
     * @return
     */
    private Map<String, OfcSoHead> split4supply(Map<String, OfcSoHead> soMap) {

        Map<String, OfcSoHead> soHeadMap = new HashMap<>();
        for (Map.Entry<String, OfcSoHead> soHeadEntry : soMap.entrySet()) {
            String soKey = soHeadEntry.getKey();
            OfcSoHead soHead = soHeadEntry.getValue();
            Integer fulfillChannel = soHead.getFulfillChannel();
            // 不是履约物美so
            if (!fulfillChannel.equals(FulfillChannel.SAAS_SC.getValue())) {
                soHeadMap.put(soKey, soHead);
                continue;
            }

            //履约模式拆单
            List<OfcSoDetail> soDetailList = soHead.getDetails();
            Set<Long> goodsCodes = new HashSet<>();
            for (OfcSoDetail soDetail : soDetailList) {
                goodsCodes.add(soDetail.getGoodsCode());
            }

            // TODO 拆单依据信息获取  商城获取
            Map<Long, Integer> splitDetailMap = new HashMap<>();
            //supplyInfoServiceProxy.getSupplyInfoByCodes(supplyCodes, soHead.getSupplierDc());

            if (null == splitDetailMap || splitDetailMap.isEmpty()) {
                throw EC.ERROR.exception(" ????????请求基础服务返回数据失败！soHead bill code  =" + soHead.getSoBillCode());
            }

            // 履约模式拆单
            for (OfcSoDetail soDetail : soDetailList) {
                Integer supplyModel = splitDetailMap.get(soDetail.getGoodsCode());
                if (null == supplyModel) {
                    throw EC.ERROR.exception("请求基础服务返回数据！没有在库直流属性 code  =" + soDetail.getGoodsCode());
                }

                String soHeadKey = soKey + ":" + supplyModel;

                OfcSoHead targetSoHead = soHeadMap.get(soHeadKey);
                if (null == targetSoHead) {
                    targetSoHead = new OfcSoHead();

                    BeanUtils.copyProperties(soHead, targetSoHead);
                    targetSoHead.setTotalSkuOrderQty(BigDecimal.ZERO);
                    targetSoHead.setDetails(new ArrayList<OfcSoDetail>());

                    JSONObject ext = JSON.parseObject(targetSoHead.getExt());
                    ext.put(Constants.SO_H_SUPPLY_MODEL, supplyModel);
                    targetSoHead.setExt(ext.toJSONString());
                    //
                    soHeadMap.put(soHeadKey, targetSoHead);
                }

                targetSoHead.getDetails().add(soDetail);
                targetSoHead.setTotalSkuOrderQty(targetSoHead.getTotalSkuOrderQty().add(soDetail.getSkuOrderQty()));
            }
        }

        for (OfcSoHead so : soHeadMap.values()) {
            int i = 0;
            for (OfcSoDetail detail : so.getDetails()) {
                detail.setItemNo((++i) * 10);
            }
        }

        return soHeadMap;
    }

    /**
     * 填充税率
     *
     * @param detail
     * @throws BusinessException
     */
    private void fillTaxRate(OfcSoDetail detail) throws BusinessException {
//        String skuSupplyCode = detail.getSkuSupplyCode();
//       BigDecimal taxRate = taxRateMap.get(skuSupplyCode);
//        if (taxRate == null) {
//            logger.warn("tax_rate is null... skuSupplyCode=" + skuSupplyCode);
//            taxRate = Constants.TAX_016;
//        }

//        detail.setTaxRate(taxRate.setScale(2, BigDecimal.ROUND_HALF_UP));

        detail.setTaxRate(Constants.TAX_016);
    }

    /**
     * 填充sku_define
     *
     * @param detail
     * @param skuDefineMap
     * @throws BusinessException
     */
    private void fillSkuDefine(OfcOrderDetail detail, Map<Long, Integer> skuDefineMap) throws BusinessException {
        Long goodsCode = detail.getGoodsCode();
        Integer skuDefine = skuDefineMap.get(goodsCode);
        if (skuDefine == null) {
            skuDefine = SkuDefine.EA.getCode();
//            throw EC.ERROR.exception("商品不存在! goods_code=" + goodsCode);
        }
        if (!SkuDefine.EA.getCode().equals(skuDefine) && !SkuDefine.BOX.getCode().equals(skuDefine) && !SkuDefine.KG.getCode().equals(skuDefine)) {
            throw EC.ERROR.exception("sku_define is error! define=" + skuDefine + ", 销售商品码=" + goodsCode);
        }
        JSONObject json;
        String ext = detail.getExt();
        if (StringUtils.hasLength(ext)) {
            json = JSON.parseObject(ext);
        } else {
            json = new JSONObject();
        }
        json.put(Constants.ORDER_D_SKU_DEFINE, skuDefine);
        detail.setExt(json.toJSONString());
    }

    /**
     * 校验并更新获取OFC客户信息
     *
     * @param order
     * @return
     * @throws BusinessException
     */
    private OfcCustomer getCustomer(OfcOrderHead order, Integer custype) throws BusinessException {
        //校验并更新用户信息
        JSONObject addressInfo = JSON.parseObject(order.getAddressInfo());
        OfcCustomer param = new OfcCustomer();
        param.setRegionCode(order.getRegionCode());
        param.setCustCode(order.getAddressCode());
        //超市名称
        param.setCustName(addressInfo.getString("market_name"));
        param.setProvince(addressInfo.getString("province_name"));
        param.setCity(addressInfo.getString("city_name"));
        param.setDistrict(addressInfo.getString("county_name"));
        param.setAddress(addressInfo.getString("address"));
        param.setContactName(addressInfo.getString("contact_name"));
        param.setContactPhone(addressInfo.getString("contact_phone"));
        //坐标
        param.setLocation(addressInfo.getString("real_position"));
        //大车限行
        Integer transLimit = addressInfo.getInteger("trans_limit");
        param.setVenderId(order.getVenderId());
        param.setExt(JSON.toJSONString(Collections.singletonMap(Constants.USER_ADDRESS_TRANS_LIMIT, transLimit)));
        param.setCusType(custype);
        return this.ofcCustomerService.updateCustomer(param);
    }
}
